#ifndef _CLIENT_HEAD_H
#define _CLIENT_HEAD_H

#include <my_header.h>
#include <syslog.h>

// 如果是正常日志，使用这个宏函数，传递打印信息
#define LOG_INFO_MSG(msg) \
    do {\
        syslog(LOG_INFO, "%s\n", msg);\
    } while(0)

// 如果是记录错误日志，使用LOG_ERR_MSG宏函数
#define LOG_ERR_MSG(msg) \
    do {\
        syslog(LOG_ERR, "%s\n", msg);\
    } while(0)

// typedef enum 
// {
//     C_OP_CD,
//     C_OP_LS,
//     C_OP_GETS,
//     C_OP_GETS_BEGIN,
//     C_OP_PUTS,
//     C_OP_PUTS_BEGIN,
//     C_OP_RMDIR,
//     C_OP_MKDIR,
//     C_OP_REMOVE,
//     C_OP_PWD, 
    
//     C_LINK_START,
//     C_LINK_CLOSE,

//     RES_CD,
//     RES_LS,
//     RES_GETS,
//     RES_GETS_SUCESS,
//     RES_GETS_FINISH,
//     RES_PUTS,
//     RES_PUTS_SUCESS,
//     RES_PUTS_FINISH,
//     RES_RMDIR,
//     RES_MKDIR,
//     RES_REMOVE,
//     RES_PWD,

//     RES_ERR_1, //用户所在虚拟目录打不开，清空客户端栈
//     RES_ERR_2 //用户操作目标目录打不开，返回错误信息
// } MSG_TYPE;
typedef enum 
{
    C_OP_CD,
    C_OP_LS,
    C_OP_GETS,
    C_OP_GETS_BEGIN,
    C_OP_GETS_SUCESS,
    C_OP_PUTS,
    C_OP_PUTS_BEGIN,
    C_OP_RMDIR,
    C_OP_MKDIR,
    C_OP_REMOVE,
    C_OP_PWD,
    
    C_LINK_START,
    C_LINK_CLOSE,

    RES_CD,
    RES_LS,
    RES_GETS,
    RES_PUTS,
    RES_GETS_SUCESS,
    RES_GETS_FINISH,
    RES_PUTS_SUCESS,
    RES_PUTS_FINISH,
    RES_RMDIR,
    RES_MKDIR,
    RES_REMOVE,
    RES_PWD,

    RES_ERR_1, //用户所在虚拟目录打不开，清空客户端栈
    RES_ERR_2 //用户操作目标目录打不开，返回错误信息
} MSG_TYPE;
typedef struct
{
    int type;
    int vir_path_len;
    char vir_path_val[1024];
    int args_len;
    char args_val[1024];
}RequestPackage;

typedef struct
{
    int type;
    int vir_path_len;
    char vir_path_val[1024];
    int args_len;
    char args_val[1024];
}ResponsePackage;

typedef struct node_S
{
    char subpath[128];
    struct node_S* front;
    struct node_S* back; 
}ClientVirtualPathNode;

typedef struct 
{
    ClientVirtualPathNode* head;
    ClientVirtualPathNode* tail;
    int size;

}ClientVirtualPathStack;

// 客户端解析器 
int send_resolver(char *statement, RequestPackage *prequest);
int recv_resolver(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack, int socked_fd);

//client_api.c
int client_cd(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack); 
int client_ls(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack);
int client_pwd(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack);
int client_mkdir(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack);
int client_rmdir(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack);
int client_rmfile(ResponsePackage *presponse,ClientVirtualPathStack* pvirtualpathstack);
int client_puts(ResponsePackage *presponse, ClientVirtualPathStack* pvirtualpathstack, int socked_fd);
int client_gets(ResponsePackage *presponse,const ClientVirtualPathStack* pvirtualpathstack,int socked_fd);

int client_puts_mmap(ResponsePackage *presponse, ClientVirtualPathStack* pvirtualpathstack, int socked_fd);
int client_gets_mmap(ResponsePackage *presponse,const ClientVirtualPathStack* pvirtualpathstack,int socked_fd);
//int client_puts_mmap2(ResponsePackage *presponse, ClientVirtualPathStack* pvirtualpathstack, int socked_fd);
int client_gets_mmap2(ResponsePackage *presponse,const ClientVirtualPathStack* pvirtualpathstack,int socked_fd);
ClientVirtualPathStack* ClientVirtualPathStack_init();
int ClientVirtualPathStack_print(ClientVirtualPathStack* p,char* str);
int ClientVirtualPathStack_push(ClientVirtualPathStack *stack,char *subpath);
int ClientVirtualPathStack_pop(ClientVirtualPathStack *stack);
int pathTostack(ClientVirtualPathStack *pstack, char *path);

int recvn(int netfd,void* buf,long len,long* pProcessed);
int sendn(int netfd,void* buf,long len,long* pProcessed);


// puts的value信息：用户要从本地上传文件的路径 用户要将上传文件存在服务器哪里的路径
// 从response包里取得 用户要从本地上传文件的路径（信息在value里，需要字符串截取）
int puts_from_path(ResponsePackage *presponse, char *puts_from_path);

// gets的value信息：用户要从服务器哪里获取文件的路径 用户要将从服务器获得的文件存到哪里的路径
// 从response包里取得 用户要将从服务器上下载的文件存到本地哪里的路径
int gets_save_path(ResponsePackage *presponse, char *gets_save_path);
// 服务端也得写，获得的信息与客户端相反
#endif
